package org.geektime.task.sboauth.request;

import org.geektime.task.sboauth.config.OAuthConfig;
import org.geektime.task.sboauth.config.OAuthSourceEnum;
import org.geektime.task.sboauth.model.OAuthCallback;
import org.geektime.task.sboauth.model.OAuthToken;
import org.geektime.task.sboauth.model.OAuthUser;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 2021年04月21日 22:32:44
 */
public abstract class AbstractOAuthRequest {

    protected OAuthConfig config;

    protected OAuthSourceEnum source;


    public AbstractOAuthRequest(OAuthConfig config,OAuthSourceEnum source) {
        this.config = config;
        this.source = source;
    }

    /**
     * 获取access token
     *
     * @param authCallback 授权成功后的回调参数
     * @return token
     * @see AbstractOAuthRequest#authorize()
     * @see AbstractOAuthRequest#authorize(String)
     */
    protected abstract OAuthToken getAccessToken(OAuthCallback authCallback);


    /**
     * 使用token换取用户信息
     *
     * @param authToken token信息
     * @return 用户信息
     * @see AbstractOAuthRequest#getAccessToken(OAuthCallback)
     */
    protected abstract OAuthUser getUserInfo(OAuthToken authToken);


    public OAuthUser login(OAuthCallback authCallback) {
        OAuthUser user = null;
        try {
            //调用子类获得access token
            OAuthToken authToken = this.getAccessToken(authCallback);

            user = this.getUserInfo(authToken);

        } catch (Exception e) {
           e.printStackTrace();
        }
        return user;
    }


    public String authorize() {
        return this.authorize(null);
    }

    /**
     * 返回带{@code state}参数的授权url，授权回调时会带上这个{@code state}
     *
     * @param state state 验证授权流程的参数，可以防止csrf
     * @return 返回授权地址
     * @since 1.9.3
     */
    public java.lang.String authorize(String state) {

        StringBuffer sb = new StringBuffer(source.authorize());
        sb.append("?");
        sb.append("response_type=code");
        sb.append("&client_id=").append(config.getClientId());
        sb.append("&redirect_uri=").append(config.getRedirectUri());
        sb.append("&state=").append(getRealState(state));
        return sb.toString();
    }

    /**
     * 返回获取accessToken的url
     *
     * @param code 授权码
     * @return 返回获取accessToken的url
     */
    protected String accessTokenUrl(String code) {
        StringBuffer sb = new StringBuffer(source.accessToken());
        sb.append("?");
        sb.append("code=").append(code);
        sb.append("&client_id=").append(config.getClientId());
        sb.append("&client_secret=").append(config.getClientSecret());
        sb.append("&grant_type=").append("authorization_code");
        sb.append("&redirect_uri=").append(config.getRedirectUri());
        return sb.toString();
    }

    /**
     * 返回获取userInfo的url
     *
     * @param authToken token
     * @return 返回获取userInfo的url
     */
    protected String userInfoUrl(OAuthToken authToken) {
        StringBuffer sb = new StringBuffer(source.userInfo());
        sb.append("?");
        sb.append("access_token=").append(authToken.getAccessToken());
        return sb.toString();
    }


    /**
     * 获取state，如果为空， 则默认取当前日期的时间戳
     *
     * @param state 原始的state
     * @return 返回不为null的state
     */
    protected String getRealState(String state) {
        if (StringUtils.isEmpty(state)) {
            state = UUID.randomUUID().toString();
        }
        return state;
    }

    /**
     * 根据Code获取accessToken结果
     * @param code
     * @return
     */
    protected String doPostAuthorizationCode(String code) {
        String content = "";
        try{
          Connection conn = Jsoup.connect(accessTokenUrl(code));
          Connection.Response resp = conn.method(Connection.Method.POST).ignoreContentType(true).header("Content-Type","application/x-www-form-urlencoded ").execute();
          content = resp.body();
        }catch (Exception e){
            e.printStackTrace();
        }
        return content;
    }


    protected String doGetUserInfo(OAuthToken authToken) {
        String content = "";
        try{
            Connection conn = Jsoup.connect(userInfoUrl(authToken));
            Connection.Response resp = conn.method(Connection.Method.GET).ignoreContentType(true).header("Content-Type","application/x-www-form-urlencoded ").execute();
            content = resp.body();
        }catch (Exception e){
            e.printStackTrace();
        }
        return content;
    }


}
